package com.kingsalert.kingsalert.view.process_widget;

import android.Manifest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;
import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.FragmentActivity;

import com.google.common.util.concurrent.ListenableFuture;
import com.kingsalert.kingsalert.R;
import com.kingsalert.kingsalert.base.BaseApplication;
import com.kingsalert.kingsalert.base.BaseProcessWidgetManager;
import com.kingsalert.kingsalert.bean.process.ProcessInfo_Data;
import com.kingsalert.kingsalert.bean.userinfo.OthersInfo;
import com.kingsalert.kingsalert.config.Constant;
import com.kingsalert.kingsalert.config.PermissionConfig;
import com.kingsalert.kingsalert.util.http.HttpUtil;
import com.kingsalert.kingsalert.util.image.ImageConvert;

import java.io.File;
import java.io.IOException;
import java.util.TreeMap;

import pub.devrel.easypermissions.EasyPermissions;


public class FaceViewManager extends BaseProcessWidgetManager {

    private final FragmentActivity activity;

    private PreviewView previewView ;
    private ImageButton imageIb;
    private ImageButton photographIb;

    private String photoUrl;

    private ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;

    private ImageCapture imageCapture;

    private String imgPath = "";

    private Runnable afterPermissionRunnable;

    private Bitmap imageBitmap;

    private final Runnable processRespRunnable,imgUploadResp;

    public FaceViewManager(View view, ProcessInfo_Data data,String page,Runnable processRespRunnable,Runnable imgUploadResp){
        super(view,data,page);
        this.activity = (FragmentActivity) view.getContext();
        this.processRespRunnable = processRespRunnable;
        this.imgUploadResp = imgUploadResp;
    }

    @Override
    protected void init(){

        previewView = mView.findViewById(R.id.vpf_view_preview);
        imageIb = mView.findViewById(R.id.vpf_ib_image);
        photographIb = mView.findViewById(R.id.vpf_ib_photograph);

        //开始人脸拍照点击
        imageIb.setOnClickListener(v -> runAfterCheckCameraPermission(this::startPhotograph));

        //拍照点击
        photographIb.setOnClickListener(v -> {
            runAfterCheckCameraPermission(() -> {
                if (!TextUtils.isEmpty(photoUrl)) startPhotograph();
                else captureImage();
            });
        });

    }

    @Override
    public boolean checkInput() {
        return false;
    }

    @Override
    public String getInput() {
        return "";
    }

    public void nextClick(String path){

        runAfterCheckCameraPermission(() -> {
            if (TextUtils.isEmpty(photoUrl)) startPhotograph();//没有照片时自动开启拍照
            else
                HttpUtil.getInstance().submitProcessInfo(
                        activity,
                        path,
                        new TreeMap<String, String>() {{put("faceImgUrl", photoUrl);}},
                        () -> HttpUtil.getInstance().userProcess(activity,() -> {if (processRespRunnable!=null) processRespRunnable.run();}
                    )
                );

        });
    }

    private void startPhotograph(){

        HttpUtil.getInstance().saveBuriedPoint(page,"START_TAKING_CLICK","");

        photoUrl = "";

        //打开拍照
        processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(mView.getContext());
        //监听摄像头的启动
        processCameraProviderListenableFuture.addListener(() -> {
            try {
                ProcessCameraProvider provider = processCameraProviderListenableFuture.get();

                previewView.setVisibility(View.VISIBLE);

                //释放资源
                provider.unbindAll();

                //创建相机选择器并选择前置摄像头
                CameraSelector cameraSelector = new CameraSelector.Builder()
                        .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                        .build();

                //创建一个相机预览对象并将其与PreviewView的SurfaceProvider绑定，实现在该组件上显示相机预览画面
                Preview preview = new Preview.Builder().build();
                preview.setSurfaceProvider(previewView.getSurfaceProvider());

                //创建一个ImageCapture对象用于拍摄照片，设置拍照模式为最小化延迟模式
                imageCapture = new ImageCapture.Builder()
                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                        .build();

                //点击图像隐藏,拍照按键显示
                imageIb.setImageBitmap(null);
                photographIb.setVisibility(View.VISIBLE);

                //启动相机并将其与当前生命周期绑定  cameraSelector用于选择相机设备，preview用于显示预览。imageCapture用于捕获图像
                if (activity!=null) provider.bindToLifecycle(activity, cameraSelector, preview, imageCapture);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }, ContextCompat.getMainExecutor(mView.getContext()));
    }

    //拍照
    private void captureImage() {

        HttpUtil.getInstance().saveBuriedPoint(page,"TAKING_PICTURE","");

        imgPath = this.getImageFilePath();
        ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(new File(imgPath)).build();
        imageCapture.takePicture(
                //指定照片保存的位置和格式
                options,
                //指定保存照片时要运行的线程
                ContextCompat.getMainExecutor(mView.getContext()),
                //指定保存照片完成后的回调函数
                new ImageCapture.OnImageSavedCallback() {
                    @Override
                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                        try {
                            Bitmap bitmap = BitmapFactory.decodeFile(imgPath);
                            imageBitmap = rotateBitmap(bitmap, imgPath);

                            if (!TextUtils.isEmpty(imgPath)) {
                                //照片压缩
                                ImageConvert.startConvertImage(
                                        new File(imgPath),
                                        (localPath, thumpImg) -> {
                                            imageBitmap = thumpImg;
                                            //上传照片
                                            new Thread(() -> HttpUtil.getInstance().uploadImg(activity,localPath,() -> {
                                                if (imgUploadResp!=null) imgUploadResp.run();
                                            })).start();
                                        }
                                );
                            } else {
                                photoUrl = null;
                                Toast.makeText(mView.getContext(),mView.getContext().getString(R.string.photo_upload_again_tip),Toast.LENGTH_SHORT).show();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onError(@NonNull ImageCaptureException exception) {
                        Toast.makeText(mView.getContext(),"Error: " + exception.getMessage(),Toast.LENGTH_SHORT).show();
                    }
                }
        );

    }

    public void onPhotoUploadResponse() {

        String imagePath = OthersInfo.getInstance().getImgPath();

        if (TextUtils.isEmpty(imagePath)) {
            Toast.makeText(mView.getContext(),mView.getContext().getString(R.string.photo_upload_again_tip),Toast.LENGTH_SHORT).show();
            return;
        }

        this.photoUrl = imagePath;

        imageIb.setImageBitmap(imageBitmap);
        previewView.setVisibility(View.GONE);
    }

    /**
     * 根据角度反转图片
     */
    public static Bitmap rotateBitmap(Bitmap bitmap, String imageFilePath) {
        try {
            ExifInterface exif = new ExifInterface(imageFilePath);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
            Matrix matrix = new Matrix();

            switch (orientation) {
                case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                    matrix.setScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    matrix.setRotate(180);
                    break;
                case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                    matrix.setRotate(180);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_TRANSPOSE:
                    matrix.setRotate(90);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    matrix.setRotate(90);
                    break;
                case ExifInterface.ORIENTATION_TRANSVERSE:
                    matrix.setRotate(-90);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    matrix.setRotate(180);
                    break;
                default:
                    return bitmap;
            }

            try {
                Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                bitmap.recycle();
                return rotatedBitmap;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    //执行前判断相机权限
    public void runAfterCheckCameraPermission(Runnable runnable){
        if (!PermissionConfig.checkPermissions(mView.getContext(), Manifest.permission.CAMERA)) {
            afterPermissionRunnable = runnable;
            if (activity!=null)
                EasyPermissions.requestPermissions(activity, mView.getContext().getString(R.string.launch_permissions_camera), PermissionConfig.PermissionCode_Camera, Manifest.permission.CAMERA);
        } else if (runnable!=null) runnable.run();

    }

    /**
     * 获取图片路径
     */
    private String getImageFilePath() {
        String pictureId = System.currentTimeMillis() + "";
        String imgDir = getSandboxFolderPath();
        return (imgDir + File.separator + pictureId + ".jpg");
    }

    /**
     * 获取沙盒路径
     */
    private String getSandboxFolderPath() {
        String inAppFolder = BaseApplication.getInstant().getFilesDir().getAbsolutePath();
        inAppFolder += File.separator;
        inAppFolder += Constant.PRODUCT;
        inAppFolder += "_PICS";

        File folderFile = new File(inAppFolder);
        if (!folderFile.exists()) {
            folderFile.mkdirs();
        }

        return inAppFolder;
    }

    public void onCameraPermissionAgree(){
        if (afterPermissionRunnable!=null) afterPermissionRunnable.run();
    }

}
